﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Web;
using System.IO;
using System.Web.Security;
using C3.Proto.Core.Model;
using C3.Proto.Core.Repository;
using C3.Proto.Core.Service;
using log4net;
using RNGCryptoServiceProvider = System.Security.Cryptography.RNGCryptoServiceProvider;
using SHA256Managed = System.Security.Cryptography.SHA256Managed;


namespace C3.Safety.Service
{
    public class UserService : ServiceBase, IUserService
    {
         public UserService(C3.Proto.Core.Service.ISessionService sessionService,IUserRepository userRepository)
            : base(sessionService)
        {
            HashProvider = new SHA256Managed();
            SalthLength = 8;
            UserRepository = userRepository;
            
        }
        private static readonly ILog Log = LogManager.GetLogger(typeof(UserService));
        private SaltedHashProvider saltedHashProvider;
        private IUserRepository UserRepository { get; set; }
        public SaltedHashProvider SaltedHashProvider
        {
            get
            {
                return saltedHashProvider ?? new SaltedHashProvider();
            }

            set {saltedHashProvider = value; }
        }
        HashAlgorithm HashProvider;
        int SalthLength;

        public TransactionResult AddCSV(int id, string doctype)
        {
            var t = new TransactionResult();
            try
            {
                var file = HttpContext.Current.Request.Files["doc"];
                
                
                var path = string.Empty;
                if (file == null) return t;
                FileInfo fInfo = new FileInfo(file.FileName);
                if (fInfo.Extension != ".csv") return t;
                var pathtype = doctype;
                path = Path.Combine(HttpContext.Current.Server.MapPath("/Assets/Imports/" + pathtype + "/"), doctype +".csv");
                file.SaveAs(path);


                var doc = new UserDocument()
                {
                    
                    Name = file.FileName,
                    UId = id,
                    CreateDate = DateTime.Now,
                    DocType = doctype
                    
                };

                ((IRepositoryBase)UserRepository).Add(doc);
                t.Successful = true;
                if (t.Successful)
                {
                    switch (doctype)
                    {
                        case "RIR": 
                            UserRepository.RirImport();
                            break;
                        case "STEP": 
                            UserRepository.StepImport();
                            break;
                        case "claims": 
                            UserRepository.ClaimsImport();
                            break;
                        case "Manhours": 
                            UserRepository.ManhoursImport();
                            break;
                        default: break;
                    }
                }

                return t;

            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return t;
            }
        }

        public TransactionResult LoginUser(string email, string password, bool remember)
        {

            var t = new TransactionResult() { Successful = false };
            try
            {
                if (!IsAuthenticated(email, password))
                    return t;

                //get user with hashed password
                var user = SessionService.CurrentUser;
                HttpContext.Current.Response.Cookies.Clear();
                FormsAuthenticationTicket authTicket;
                var exp = DateTime.Now.AddMinutes(120);
                if (remember)
                {
                    DateTime.Now.AddMonths(3);
                }

                authTicket = new FormsAuthenticationTicket(2, user.Email,
                                                               DateTime.Now, exp, true, user.Roles);
                // Now encrypt the ticket.
                var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                // Create a cookie and add the encrypted ticket to the 
                // cookie as data.
                var authCookie =
                    new HttpCookie(FormsAuthentication.FormsCookieName,
                                   encryptedTicket);
                authCookie.Expires = exp;
                HttpContext.Current.Response.Cookies.Add(authCookie);

                t.Successful = true;

                t.ReturnVal = new { user.Id, user.Roles };
                return t;
            }
            catch (Exception ex)
            {

                Log.Error(ex);
                t.Exception = ex.Message;
                return t;

            }

        }
        
        public string SaltAndHashPassword(User u)
        {
            string hash,salt;
            SaltedHashProvider.GetHashAndSaltString(u.Password,out hash,out salt);
            u.Salt = salt;
            return hash;
        }
        
        private bool IsAuthenticated(string email, string password)
        {
            /*   1. The users enters the password
                 2. The system looks up the stored hash + salt
                 3. The system tries if a new hash of the given password + salt matches the stored hash
                 4. If they match the user can login 
             */
            var u = UserRepository.GetUserByEmail(email);
            if (u==null)
                return false;
            var auth = SaltedHashProvider.VerifyHashString(password, u.Password, u.Salt);
            if (auth)
            {
                SessionService.CurrentUser = u;
            }
            return auth;
        }
        
        public void LogoutUser()
        {
            FormsAuthentication.SignOut();
            HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName].Expires = DateTime.Now;
            HttpContext.Current.Session.Abandon();
        }

        public User GetUserBy(int id)
        {
            try
            {
                return ((IRepositoryBase) UserRepository).GetById<User>(id);

            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
                return new User();
            }
        }

        public User GetUserByEmail(string email)
        {
            try
            {

                return UserRepository.GetUserByEmail(email);


            }
            catch (Exception ex)
            {

                Log.Error(ex);

                return null;
            }
        }

       
        public TransactionResult AddUser(string firstname, string lastname, string email, string password)
        {
            var t = new TransactionResult() { Successful = false };
            try
            {
                var u = new User()
                            {
                               
                                FirstName = firstname,
                                LastName = lastname,
                                Email = email,
                                Password = password,
                                
                                CreateDate = DateTime.Now,
                                ModifiedDate = DateTime.Now
                            };
                u.Password = SaltAndHashPassword(u);
                ((IRepositoryBase)UserRepository).Add(u);
                t.Successful = true;
                return t;
            }
            catch (Exception ex)
            {

                Log.Error(ex);
                t.Exception = ex.Message;
                return t;

            }
        }

        public TransactionResult EditUser(int id, string firstname, string lastname, string email, string password)
        {
            var t = new TransactionResult() { Successful = false };
            try
            {

                var u = ((IRepositoryBase) UserRepository).GetById<User>(id);
                if(!string.IsNullOrEmpty(password))
                {
                    u.Password = password;
                    u.Password = SaltAndHashPassword(u);
                }
                
                u.FirstName = firstname;
                u.LastName = lastname;
                u.Email = email;
               
                u.ModifiedDate = DateTime.Now;
                ((IRepositoryBase)UserRepository).Update(u);
                t.Successful = true;

                return t;
            }
            catch (Exception ex)
            {

                Log.Error(ex);
                t.Exception = ex.Message;
                return t;

            }
        }

        public TransactionResult ChangePassword(int id, string password)
        {
            var t = new TransactionResult() { Successful = false };
            try
            {
                var user = ((IRepositoryBase)UserRepository).GetById<User>(id);
                user.Password = password;
                user.Password = SaltAndHashPassword(user);
                ((IRepositoryBase)UserRepository).Update(user);
                t.Successful = true;
                return t;


            }
            catch (Exception ex)
            {

                Log.Error(ex);
                t.Exception = ex.Message;
                return t;
            }
        }

    }
}


